#pragma once
#include<iostream>
using namespace std;
namespace wang
{
	template<class T>
	struct list_node
	{
		list_node<T>* _next;
		list_node<T>* _prev;
		T _value;
		list_node(const T& value = T())
			: _next(nullptr)
			,_prev(nullptr)
			,_value(value)
		{}
	};
	template<class T,class Ref,class Ptr>
	struct list_iterator
	{
		typedef list_iterator< T, Ref,  Ptr> Self;
		typedef list_node<T> Node;
		list_iterator(Node* node)
			:_node(node)
		{}
		Self& operator++()
		{   
			_node = _node->_next;
			return *this;
		}
		Self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		Ref operator*()
		{
			return _node->_value;
		}
		Ptr operator->()
		{
			return &_node->_value;
		}
		bool operator!=(const Self& s) const
		{
			return _node != s._node;
		}
		bool operator==(const Self& s) const
		{
			return _node == s._node;
		}
		Node* _node;
	};
	template<class T>
	class list
	{
	public:
		typedef list_node<T> Node;
		typedef list_iterator<T, T&, T*> iterator;
		typedef list_iterator<T, const T&, const T*> const_iterator;
		void Init()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
			_head->_value = -1;
		}
		void swap(list<int> lt)
		{
			std::swap(_head,lt._head);
			std::swap(_size, lt._size);
		}
		list()
		{
			Init();
		}
		list(list<T>& lt)
		{   
			Init();
			auto it = lt.begin();
			while (it != lt.end())
			{
				push_back(it._node->_value);
				++it;
			}
		}
		list<int>& operator=(list<T> lt)
		{
			swap(lt);
			return *this;
		}
		iterator begin()
		{
			return _head->_next;
		}
		iterator end()
		{
			return _head;
		}
		const_iterator begin()const
		{
			return _head->_next;
		}
		const_iterator end()const 
		{
			return _head;
		}
		size_t size()
		{
			return _size;
		}
		bool empty()
		{
			return _size == 0;
		}
		Node* insert(iterator pos,T value)
		{
			Node* newnode = new Node(value);
			Node* cur = pos._node;
			Node* prev = pos._node->_prev;
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			_size++;
			return newnode;
		}
		void push_back(T value)
		{
			auto it = end();
			insert(it, value);
		}
		iterator erase(iterator pos)
		{
			Node* prev = pos._node->_prev;
			Node* next = pos._node->_next;
			delete pos._node;
			prev->_next = next;
			next->_prev = prev;
			--_size;
			return  next;
		}
	private:
		Node* _head;
		size_t _size;
	};
	template <class Container>
	void print_container(Container& v)
	{   
		
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}
	void test1()
	{
		list<int> lt1;
		lt1.push_back(1);
		lt1.push_back(2);
		lt1.push_back(3);
		lt1.push_back(4);
		lt1.push_back(5);
		print_container(lt1);
		list<int> lt2 = lt1;
		print_container(lt2);
		auto it = lt1.begin();
		it=lt1.erase(it);
		lt1.erase(it);  
		print_container(lt1);
	}
	void test2()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);
		lt.push_back(5);
		list<int>::iterator it = lt.begin();
		lt.insert(it, 10);
		*it += 100;
		print_container(lt);
	}
}